package tool

import java.io.File
import java.nio.file.Files
import dao.ModeDao

import javax.inject.Inject
import models.Tables.UserRow
import org.apache.commons.lang3.StringUtils
import org.joda.time.DateTime
import play.api.mvc._
import utils.{DesEncrypter, Utils}

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import models.Tables._
import org.slf4j.LoggerFactory
import play.api.http.HttpVerbs
import play.api.libs.json.{JsValue, Json}
import shared.{Shared}

import scala.math.BigDecimal.RoundingMode
import implicits.Implicits._
import play.api.data.{Form, FormBinding}
import shared.pojo.Pojo.ResultData
import shared.pojo.Predict.PredictData

/**
 * Created by yz on 2018/8/23
 */
class Tool @Inject()(modeDao: ModeDao) {

  def getUserName(implicit request: RequestHeader) = {
    request.session.get(Shared.userStr).get
  }

  def getTimes(times: Option[Int]) = times.map(_.toString).getOrElse("不限")

  def dataTime2String(dateTime: Option[DateTime]) = dateTime.map(_.toString("yyyy-MM-dd HH:mm:ss")).getOrElse("不限")

  def isb(user: UserRow) = user.remainTimes.map(_ > 0).getOrElse(true) && user.startTime.map(_.isBeforeNow).getOrElse(true) &&
    user.endTime.map(_.isAfterNow).getOrElse(true)

  val newPasswordDesEncrypter = new DesEncrypter("newPassword12345")

  val registerDesEncrypter = new DesEncrypter("register12345678")

  def createTempDirectory(prefix: String) = {
    if (isTestMode) Utils.testDir else Files.createTempDirectory(prefix).toFile
  }

  def isTestMode = {
    val mode = Utils.execFuture(modeDao.select)
    if (mode.test == "t") true else false
  }

  def deleteDirectory(direcotry: File) = {
    if (!isTestMode) Utils.deleteDirectory(direcotry)
  }

  def getPredictValue(file: File): Map[String, String] = {
    val lines = file.lines
    getPredictValue(lines)
  }

  def getPredictValue(lines: List[String]): Map[String, String] = {
    val headers = lines.head.split("\t")
    headers.zip(lines(1).split("\t")).toMap
  }

  def getResultData(file: File) = {
    val map = getPredictValue(file)
    ResultData(BigDecimal(map("Case")), BigDecimal(map("Cirrhosis")), BigDecimal(map("Late")))
  }

  def getExtraData(file: File) = {
    val map = getPredictValue(file)
    ExtraDataF(unit = getValue(map, "送检单位"), address = getValue(map, "地址"),
      name = getValue(map, "姓名"), sex = getValue(map, "性别"),
      office = getValue(map, "送检科室"), doctor = getValue(map, "申请医生"),
      number = getValue(map, "门诊/住院号"), sampleTime = getValue(map, "采样时间"),
      submitTime = getValue(map, "送检时间"), sampleType = getValue(map, "样本类型"),
      sampleStatus = getValue(map, "样本状态"), title = getValue(map, "标题"),
      reporter = getValue(map, "检验人"), checker = getValue(map, "审核人"),
      checkDate = getValue(map, "检验日期"), reportDate = getValue(map, "报告日期"),
      testMethod = getValue(map, "检验方法")
    )
  }

  def getValue(map: Map[String, String], header: String) = {
    val str = map.getOrElse(header, "NA")
    if (str == "NA") "" else str
  }


  def getResultData(lines: List[String]) = {
    val map = getPredictValue(lines)
    ResultData(BigDecimal(map("Case")), BigDecimal(map("Cirrhosis")), BigDecimal(map("Late")))
  }

  def getOrinalData(file: File): OrignalData = {
    getOrinalData(file.lines)
  }

  def getOrinalData(lines: List[String]) = {
    val map = getPredictValue(lines)
    OrignalData(sampleId = map("SampleID"), age = map("Age"), ast = map("AST"), alt = map("ALT"),
      plt = map("PLT"), tyr = map("Tyr"), tca = map("TCA"), phe = map("Phe"), trp = map("Trp"), valine = map("Val"),
      ca = map("CA"), met = map("Met"), gca = map("GCA"), gcdca = map("GCDCA"), tcdca = map("TCDCA"))
  }

  def getShow(resultData: ResultData) = {
    var show = "1"
    if (resultData.caseDouble > 0.5) {
      show = "2"
      if (resultData.cirrhosis <= 0.5) {
        show = "3"
      }
    }
    show
  }

  def scale100(x: BigDecimal) = {
    val scale = x.scale - 2
    val finalScale = if (scale >= 0) scale else 0
    (x * 100).setScale(finalScale, RoundingMode.HALF_UP)
  }

  def getMissionJson(row: MissionRow, resultData: ResultData) = {
    val missionMap = Utils.getMapByT(row)
    Json.toJson(missionMap)
  }

  def getUserId(implicit request: RequestHeader) = {
    request.session.get("forest_id").get.toInt
  }

  def getUserIdDir(userId: Int) = {
    new File(Utils.userDir, userId.toString)
  }

  def getUserMissionDir(userId:Int) = {
    val userIdDir = getUserIdDir(userId)
    new File(userIdDir, "mission")
  }

  def getMissionIdDirById(missionId: Int,userId:Int) = {
    val userMissionFile = getUserMissionDir(userId)
    new File(userMissionFile, missionId.toString)
  }

  def getUserIdDir(implicit request: RequestHeader) = {
    val userId = getUserId
    new File(Utils.userDir, userId.toString)
  }

  case class MyMessage(valid: Boolean, message: String)

  def getEmptyExtraDataRow(id: Int, userId: Int) = {
    ExtraDataRow(id = id, userId = userId, sampleId = "", unit = "", address = "", name = "", sex = "", office = "",
      doctor = "", number = "", sampleTime = "", submitTime = "", sampleType = "", sampleStatus = "", title = "",
      danger = "", reporter = "", checker = "", checkDate = "", reportDate = "", testMethod = "")
  }

}

object Tool {

  val logger = LoggerFactory.getLogger(this.getClass)

  def jsonParse(jsValue: JsValue) = FormUtils.fromJson(jsValue, Form.FromJsonMaxChars).mapValues(Seq(_))

  def multipartFormParse(body: MultipartFormData[_]) = body.asFormUrlEncoded

  def transformRq(implicit request: Request[AnyContent], formBinding: FormBinding) = {

    val unwrap = request.body match {
      case body: play.api.mvc.AnyContent =>
        body.asFormUrlEncoded.orElse(body.asMultipartFormData).orElse(body.asJson).getOrElse(body)
      case body => body
    }
    val data: Map[String, Seq[String]] = unwrap match {
      case body: Map[_, _] => body.asInstanceOf[Map[String, Seq[String]]]
      case body: MultipartFormData[_] => multipartFormParse(body)
      case Right(body: MultipartFormData[_]) => multipartFormParse(body)
      case body: play.api.libs.json.JsValue => jsonParse(body).toMap
      case _ => Map.empty
    }
    val method: Map[_ <: String, Seq[String]] = request.method.toUpperCase match {
      case HttpVerbs.POST | HttpVerbs.PUT | HttpVerbs.PATCH => Map.empty
      case _ => request.queryString
    }
    val obj = (data ++ method).foldLeft(ujson.Obj()) {
      case (s, (key, values)) =>
        if (key.endsWith("[]")) {
          val k = key.dropRight(2)
          s ++ ujson.Obj(k -> values)
        } else {
          s ++ ujson.Obj(key -> values.headOption.getOrElse(""))
        }
    }
    logger.info(s"${obj}")
    obj
  }

  def dataCheck(data: PredictData) = {
    PredictDataValidTool.valid(data)
  }


}
